package com.tianji.learning.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.tianji.common.autoconfigure.mq.RabbitMqHelper;
import com.tianji.common.constants.CacheConstants;
import com.tianji.common.constants.MqConstants;
import com.tianji.common.domain.dto.PointMsgDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.entity.SignRecord;
import com.tianji.learning.domain.vo.SignResultVO;
import com.tianji.learning.mapper.SignRecordMapper;
import com.tianji.learning.service.ISignRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 签到记录表 服务实现类
 * </p>
 *
 * @author author
 */
@Service
public class SignRecordServiceImpl extends ServiceImpl<SignRecordMapper, SignRecord> implements ISignRecordService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    RabbitMqHelper mqHelper;

    @Override
    public List<Integer> getSignRecords() {
        Long userId = UserContext.getUser();
        String key = getSignRecordKey(userId);
        int offset = LocalDateTime.now().getDayOfMonth();
        List<Long> dayList = redisTemplate.opsForValue().bitField(key,
                BitFieldSubCommands.create(BitFieldSubCommands.BitFieldGet.create(
                        BitFieldSubCommands.BitFieldType.unsigned(offset), BitFieldSubCommands.Offset.offset(0)
                )));
        List<Integer> list = new ArrayList<>(offset);
        // 补0
        String bitList = Long.toBinaryString(dayList.get(0));
        for(int i=0; i<(offset - bitList.length());i++){
            list.add(0);
        }
        for(int i=0; i<bitList.length();i++){
            list.add(Integer.valueOf(""+bitList.charAt(i)));
        }
        return list;
    }

    @Override
    public SignResultVO sign() {
        Long userId = UserContext.getUser();
        String key = getSignRecordKey(userId);
        int offset = LocalDateTime.now().getDayOfMonth();
        Boolean oldVale = redisTemplate.opsForValue().setBit(key, offset - 1, true);
        if (oldVale) {
            throw new BizIllegalException("今天已经签到过了");
        }
        SignResultVO signResultVO = new SignResultVO();
        //判断是否连续签到
        List<Long> dayList = redisTemplate.opsForValue().bitField(key,
                BitFieldSubCommands.create(BitFieldSubCommands.BitFieldGet.create(
                        BitFieldSubCommands.BitFieldType.unsigned(offset), BitFieldSubCommands.Offset.offset(0)
                )));
        if (CollectionUtil.isNotEmpty(dayList) && dayList.size() > 0) {
            int signDays = 0;
            int rewardPoints = 0;
            Long singRecordList = dayList.get(0);
            String bitList = Long.toBinaryString(singRecordList);
            for(int i=bitList.length()-1; i>=0; i--){
                char bit = bitList.charAt(i);
                if(bit == '1'){
                    signDays++;
                } else {
                    break;
                }
            }
            if (signDays == 7) {
                rewardPoints = 10;
            } else if (signDays == 14) {
                rewardPoints = 20;
            } else if (signDays == 28) {
                rewardPoints = 40;
            }
            signResultVO.setSignDays(signDays);
            signResultVO.setRewardPoints(rewardPoints);

            PointMsgDTO msg = new PointMsgDTO(userId, rewardPoints+1);
            mqHelper.send(MqConstants.Exchange.LEARNING_EXCHANGE,MqConstants.Key.SIGN_IN, msg);
            return signResultVO;
        }
        //返回积分
        return signResultVO;
    }

    private String getSignRecordKey(Long userId) {
        return CacheConstants.SIGN_RECORD + LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy-MM") + ":" + userId;
    }
}
